package demo.common.interceptor;

import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSON;

import demo.Result;

/**
 * http://ethansun.net/2015/01/11/spring-controller-interceptor/
 * @author wgc
 *
 */
public class LogInterceptor implements MethodInterceptor {

	private Logger logger = LoggerFactory.getLogger(getClass());

	@Override
	public Object invoke(MethodInvocation invocation) throws Throwable {
		logger.info("===================== LogInterceptor =====================");
		
		Result result = new Result();
//		String result = "";
		String paramsStr = "";
//		Object value = null;
		Method md = invocation.getMethod();
		ResponseBody annotation = md.getAnnotation(ResponseBody.class);
		try {
			Object[] args = invocation.getArguments();
			paramsStr = this.logRequest(args);
			if (annotation != null) {
				result = (Result) invocation.proceed();
			} else {
				invocation.proceed();
			}
		} catch (Throwable e) {
			/*
			 * if (e instanceof ServiceException) { Logger.error(...,
			 * ((ServiceException) e).getAlarmId(), md
			 * .getDeclaringClass().getSimpleName() + "." + md.getName() +
			 * " || " + paramsStr + " || " + printStackTraceToString(e)); } else
			 * { Logger.error(..., "some_alarm_id", md
			 * .getDeclaringClass().getSimpleName() + "." + md.getName() +
			 * " || " + paramsStr + " || " + printStackTraceToString(e)); }
			 */
		}
		
		/*
		 * 需求：
		 * 1. 打印调用方法
		 * 2. 打印请求参数
		 * 3. 如果方法有 @ResponseBody 注解，则打印返回结果
		 */
		StringBuffer sb = new StringBuffer();
		sb.append(md.getDeclaringClass().getSimpleName()).append("#").append(md.getName());
		
		logger.info("调用方法：{}", sb.toString());
		logger.info("请求参数：{}", paramsStr);
		if (annotation != null) {
			logger.info("返回结果：{}", JSON.toJSONString(result));
		}
		
//		this.logRequestResponse(md, paramsStr, result);
		
		return result;
	}

	private String logRequest(Object[] args) {
		if (args == null) {
			return "";
		}
		// 请求参数日志信息
		Map<String, Object> params = new HashMap<String, Object>();
		// int i = 1;
		for (Object arg : args) {
			if (!(arg instanceof BindingResult) && !(arg instanceof ModelMap)
					&& !(arg instanceof Model)) {
				if (arg instanceof HttpServletRequest) {
					HttpServletRequest httpRequest = (HttpServletRequest) arg;
					Enumeration<?> enume = httpRequest.getParameterNames();
					if (null != enume) {
						while (enume.hasMoreElements()) {
							Object element = enume.nextElement();
							if (null != element) {
								String paramName = (String) element;
								String paramValue = httpRequest.getParameter(paramName);
								params.put(paramName, paramValue);
							}
						}
					}
				} /*
				 * else { try { params.put("arg" + i, JsonUtil.toJson(arg));
				 * i++; } catch (Throwable e) { Logger.warn(...,
				 * "CANNOT trasform to json string:" +
				 * arg.getClass().getName()); } }
				 */
			}
		}
		String paramsStr = JSON.toJSONString(params);
		return paramsStr;
	}

//	private void logRequestResponse(Method md, String paramsStr, Result result) {
////		logMap.put("controller.method", md.getDeclaringClass().getSimpleName() + "." + md.getName());
//		StringBuffer sb = new StringBuffer();
//		sb.append(md.getDeclaringClass().getSimpleName()).append("#").append(md.getName());
//		
//	}

	/*private String printStackTraceToString(Throwable e) {
		StringWriter sw = new StringWriter();
		PrintWriter pw = new PrintWriter(sw);
		e.printStackTrace(pw);
		return sw.toString().replace("\n", " ").replace("\r", " ")
				.replace("\t", " ");
	}*/

}
